package utils

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/beego/beego/v2/core/logs"
)

// MeituanAPI 美团开放平台API客户端
type MeituanAPI struct {
	AppKey    string
	AppSecret string
	PoiId     string
	BaseURL   string
}

// NewMeituanAPI 创建美团API客户端
func NewMeituanAPI(appKey, appSecret, poiId string) *MeituanAPI {
	return &MeituanAPI{
		AppKey:    appKey,
		AppSecret: appSecret,
		PoiId:     poiId,
		BaseURL:   "https://api-open-cater.meituan.com", // 美团外卖开放平台API地址
	}
}

// 生成签名
func (m *MeituanAPI) generateSign(params map[string]string) string {
	// 按照参数名ASCII码从小到大排序
	var keys []string
	for k := range params {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	// 拼接参数名与参数值
	var buffer bytes.Buffer
	for _, k := range keys {
		buffer.WriteString(k)
		buffer.WriteString(params[k])
	}

	// 在最后拼接上应用的Secret
	buffer.WriteString(m.AppSecret)

	// 对拼接后的字符串进行MD5运算，并转为大写
	sum := md5.Sum(buffer.Bytes())
	return strings.ToUpper(hex.EncodeToString(sum[:]))
}

// 构建公共请求参数
func (m *MeituanAPI) buildCommonParams() map[string]string {
	params := make(map[string]string)
	params["app_key"] = m.AppKey
	params["timestamp"] = strconv.FormatInt(time.Now().Unix(), 10)
	return params
}

// GetOrders 获取订单列表
func (m *MeituanAPI) GetOrders(startTime, endTime time.Time) ([]map[string]interface{}, error) {
	// 构建API请求参数
	params := m.buildCommonParams()
	params["poi_id"] = m.PoiId
	params["start_time"] = startTime.Format("2006-01-02 15:04:05")
	params["end_time"] = endTime.Format("2006-01-02 15:04:05")

	// 生成签名
	params["sign"] = m.generateSign(params)

	// 构建请求URL
	url := fmt.Sprintf("%s/api/v1/order/list", m.BaseURL)

	// 发送HTTP请求
	resp, err := m.sendRequest(url, params)
	if err != nil {
		logs.Error("请求美团订单列表失败: %v", err)
		return nil, err
	}

	// 解析结果
	var result struct {
		Code int `json:"code"`
		Data struct {
			Orders []map[string]interface{} `json:"orders"`
		} `json:"data"`
		Msg string `json:"msg"`
	}

	err = json.Unmarshal(resp, &result)
	if err != nil {
		logs.Error("解析美团订单列表响应失败: %v", err)
		return nil, err
	}

	if result.Code != 0 {
		logs.Error("美团订单列表API返回错误: %s", result.Msg)
		return nil, fmt.Errorf("美团API错误: %s", result.Msg)
	}

	return result.Data.Orders, nil
}

// UpdateOrderStatus 更新订单状态
func (m *MeituanAPI) UpdateOrderStatus(orderId string, status int) error {
	// 构建API请求参数
	params := m.buildCommonParams()
	params["poi_id"] = m.PoiId
	params["order_id"] = orderId
	params["status"] = strconv.Itoa(status)

	// 生成签名
	params["sign"] = m.generateSign(params)

	// 构建请求URL
	url := fmt.Sprintf("%s/api/v1/order/status/update", m.BaseURL)

	// 发送HTTP请求
	resp, err := m.sendRequest(url, params)
	if err != nil {
		logs.Error("更新美团订单状态失败: %v", err)
		return err
	}

	// 解析结果
	var result struct {
		Code int    `json:"code"`
		Msg  string `json:"msg"`
	}

	err = json.Unmarshal(resp, &result)
	if err != nil {
		logs.Error("解析美团订单状态更新响应失败: %v", err)
		return err
	}

	if result.Code != 0 {
		logs.Error("美团订单状态更新API返回错误: %s", result.Msg)
		return fmt.Errorf("美团API错误: %s", result.Msg)
	}

	return nil
}

// 发送HTTP请求
func (m *MeituanAPI) sendRequest(url string, params map[string]string) ([]byte, error) {
	// 将参数转换为JSON
	jsonData, err := json.Marshal(params)
	if err != nil {
		return nil, err
	}

	// 创建HTTP请求
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, err
	}

	// 设置请求头
	req.Header.Set("Content-Type", "application/json")

	// 发送请求
	client := &http.Client{
		Timeout: 10 * time.Second,
	}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 读取响应内容
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}
